﻿using System;
using System.Collections.Generic;
using System.Linq;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ProductService
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            //services.AddAuthentication("Bearer")
            //    .AddIdentityServerAuthentication(options =>
            //    {
            //        options.Authority = "http://127.0.0.1:10101";
            //        options.RequireHttpsMetadata = false;
            //    });

            List<AgentService> agentId4Services = new List<AgentService>();

            using (ConsulClient consulClient = new ConsulClient(x =>
            {
                x.Address = new Uri("http://127.0.0.1:8500");
            }))
            {
                Dictionary<string, AgentService> consulServices = consulClient.Agent.Services().Result.Response;

                agentId4Services = consulServices.Values.Where(x =>
                x.Service.Equals("IdentityServer4V2Service", StringComparison.OrdinalIgnoreCase)).ToList();
            }


            if (agentId4Services != null && agentId4Services.Count > 0)
            {

                int randomId4ServiceIndex = DateTime.Now.Second % agentId4Services.Count();
                AgentService randomId4Service = agentId4Services.ElementAt(randomId4ServiceIndex);

                services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(options =>
                    {
                        options.Authority = $"http://{randomId4Service.Address}:{randomId4Service.Port}";
                        options.RequireHttpsMetadata = false;
                    });
            }
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAuthentication();

            app.UseMvc();

            string ip = Configuration["ip"];
            string port = Configuration["port"];
            string serviceName = "ProductService";
            string serviceId = $"{serviceName}:{Guid.NewGuid()}";

            using (ConsulClient consulClient = new ConsulClient(ConsulConfig))
            {
                AgentServiceRegistration service = new AgentServiceRegistration()
                {
                    ID = serviceId,
                    Name = serviceName,
                    Address = ip,
                    Port = Convert.ToInt32(port),
                    Check = new AgentServiceCheck()
                    {
                        HTTP = $"http://{ip}:{port}/api/health",
                        Interval = TimeSpan.FromSeconds(10),
                        Timeout = TimeSpan.FromSeconds(5),
                        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5)
                    }
                };
                consulClient.Agent.ServiceRegister(service).Wait();
            }

            applicationLifetime.ApplicationStopped.Register(() =>
            {
                using (ConsulClient consulClient = new ConsulClient(ConsulConfig))
                {
                    consulClient.Agent.ServiceDeregister(serviceId).Wait();
                }
            });
        }

        private void ConsulConfig(ConsulClientConfiguration config)
        {
            config.Address = new Uri("http://127.0.0.1:8500");
            config.Datacenter = "dc2";
        }
    }
}
